iT邦幫忙

2022 iThome 鐵人賽

DAY 22
1

今天我們長話短說,Composite模式主要是希望可以透過同樣的型式對每個物件做操作,並且在操控的物件中是有保持著一種層級關係。以今天的例子來說,我想要只透過一個抽象類別,去表示出老闆以及他的下屬或者更下層階級的關係,就可以使用 Composite模式。

Composite - 定義

將物件以樹形結構組織起來,以達成「部分-整體」的層次結構,使得用戶端對單個物件和組合物件的使用具有一致性。

https://ithelp.ithome.com.tw/upload/images/20220927/20136443ak7n4yQHpy.png

(圖片來源:https://en.wikipedia.org/wiki/Composite_pattern#/media/File:Composite_UML_class_diagram_(fixed).svg)

範例 UML

https://ithelp.ithome.com.tw/upload/images/20220927/20136443k70K9ceVj7.png

Code要點

  • EmployeeComponent為抽象類別,也就是所有人的基底,不管事老闆或者下屬,都是透過Employee去繼承這個抽象類別,可以看到裡面有一個屬性SubordinatesList<EmployeeComponent>,代表了這個抽象類別會再去聚合它自己,因此才能達到階層的關係。

不囉嗦上Code!

using System;
using System.Collections.Generic;
using System.Linq;

namespace DAY22_Composite
{
    internal class Program
    {
        static void Main(string[] args)
        {
            Employee CEO = new Employee("Howard", "CEO", 30000);

            Employee headSales = new Employee("Sandy", "Head Sales", 20000);
            Employee headMarketing = new Employee("Sue", "Head Marketing", 20000);

            Employee salesExecutive1 = new Employee("Richard", "Sales", 10000);
            Employee salesExecutive2 = new Employee("Johnson", "Sales", 10000);

            Employee marketingExecutive1 = new Employee("Leo", "Marketing", 10000);
            Employee marketingExecutive2 = new Employee("Bob", "Marketing", 10000);

            Employee clerk1 = new Employee("clerk1", "base", 100);
            Employee clerk2 = new Employee("clerk2", "base", 100);

            // 一層包一層
            CEO.Add(headSales);
            CEO.Add(headMarketing);

            headSales.Add(salesExecutive1);
            headSales.Add(salesExecutive2);

            headMarketing.Add(marketingExecutive1);
            headMarketing.Add(marketingExecutive2);

            marketingExecutive1.Add(clerk1);
            marketingExecutive2.Add(clerk2);

            var subordinates = CEO.GetSubordinates();
            // 查看 CEO 所有的下屬以及階層關係
            Show(subordinates, CEO.Name);
        }

        public static void Show(List<EmployeeComponent> employees, string bossName, int level = 1)
        {
            int _level = level;
            foreach (var x in employees.Select((value, index) => new { index, value }))
            {
                // 使用遞迴做 List 輸出
                Console.WriteLine($"下屬第{_level}階 |直屬上司: {bossName} |姓名:{x.value.Name}, 部門:{x.value.Dept}, 薪水:${x.value.Salary}");
                Show(x.value.Subordinates, x.value.Name, ++_level);
                --_level;
            }
        }
    }

    public abstract class EmployeeComponent
    {
        public string Name { get; set; }
        public string Dept { get; set; }
        public int Salary { get; set; }
        public List<EmployeeComponent> Subordinates { get; set; }
        public abstract void Add(EmployeeComponent employee);
        public abstract void Remove(EmployeeComponent employee);
        public abstract List<EmployeeComponent> GetSubordinates();
    }

    public class Employee : EmployeeComponent
    {
        public Employee(string name, string dept, int salary)
        {
            Name = name;
            Dept = dept;
            Salary = salary;
            Subordinates = new List<EmployeeComponent>();
        }

        public override void Add(EmployeeComponent employee)
        {
            Subordinates.Add(employee);
        }

        public override void Remove(EmployeeComponent employee)
        {
            Subordinates.Remove(employee);
        }

        public override List<EmployeeComponent> GetSubordinates()
        {
            return Subordinates;
        }
    }
}
  • 結果

https://ithelp.ithome.com.tw/upload/images/20220927/201364435jfLlagglS.png

簡單的小結

透過 Composite模式,我們可以在抽象類別中再去聚合自己,因此不用在乎究竟要處理的物件是一種個體物件或者是組成物件,都只要針對其所定義的一致介面進行操作即可。


上一篇
【DAY21】Prototype模式 - 無限複製的秘訣!
下一篇
【DAY23】Flyweight模式 - 共享的意義
系列文
勇闖秘境!探索物件導向背後的設計模式30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言